package command

import (
	"image"
	"image/color"
	"image/draw"
	"image/jpeg"

	// auto load image
	_ "image/gif"
	_ "image/png"
	"imgtools/lib/file"
	"imgtools/lib/log"
	"os"
	"path"
	"strings"

	"github.com/nfnt/resize"
	"github.com/urfave/cli/v2"
)

func dealFile(f string, opt jpgOptions) error {
	fi, _ := os.Open(f)
	defer fi.Close()

	img, _, err := image.Decode(fi)
	if err != nil {
		return err
	}

	bounds := img.Bounds()
	imgTmp := image.NewRGBA(bounds)
	draw.Draw(imgTmp, bounds, image.NewUniform(color.White), image.Point{}, draw.Over)
	draw.Draw(imgTmp, bounds, img, image.Point{}, draw.Over)

	var imgSrc image.Image = imgTmp
	if opt.width > 0 || opt.height > 0 {
		imgSrc = resize.Resize(opt.width, opt.height, imgSrc, resize.NearestNeighbor)
	}

	outdir := opt.outdir
	if outdir == "" {
		outdir = path.Join(path.Dir(f), "result")
	}

	file.Mkdirp(outdir)

	fileName := path.Base(f)
	fileName = strings.ReplaceAll(fileName, path.Ext(fileName), ".jpg")
	target := path.Join(outdir, fileName)

	fo, e := os.OpenFile(target, os.O_CREATE|os.O_WRONLY, os.ModePerm)
	if e != nil {
		return e
	}
	defer fo.Close()

	if err := jpeg.Encode(fo, imgSrc, &jpeg.Options{Quality: opt.quality}); err != nil {
		return err
	}

	log.Printfln("处理[%s]成功", target)

	return nil

}

type jpgOptions struct {
	width   uint
	height  uint
	quality int
	outdir  string
}

// JPG 处理成jpg
var JPG = &cli.Command{
	Name:        "jpg",
	Usage:       "jpg [options] [input]",
	Description: "把其它格式图片处理成jpg",
	Flags: []cli.Flag{
		&cli.UintFlag{
			Name:    "width",
			Aliases: []string{"tw"},
			Usage:   "重置的宽度",
		},
		&cli.UintFlag{
			Name:    "height",
			Aliases: []string{"th"},
			Usage:   "重置的高度",
		},
		&cli.IntFlag{
			Name:    "quality",
			Value:   80,
			Aliases: []string{"q"},
			Usage:   "重置的质量",
		},
		&cli.StringFlag{
			Name:    "outdir",
			Aliases: []string{"o"},
			Usage:   "结果图片保存目录",
		},
	},
	Action: func(c *cli.Context) error {
		quality := c.Int("quality")
		if quality < 0 || quality > 100 {
			quality = 80
		}
		opt := jpgOptions{
			width:   c.Uint("width"),
			height:  c.Uint("height"),
			quality: quality,
			outdir:  c.String("outdir"),
		}

		list := c.Args().Slice()
		if len(list) == 0 {
			log.Printfln("请输入要处理的文件或目录")
		}
		for _, input := range list {
			if !file.IsFileExists(input) {
				log.Printfln("[%s]不存在", input)
				continue
			}

			if s, e := os.Stat(input); e == nil {
				if s.IsDir() {
					if list, e := os.ReadDir(input); e == nil {
						for _, fi := range list {
							if fi.IsDir() {
								continue
							}
							fiPath := path.Join(input, fi.Name())
							if e := dealFile(fiPath, opt); e != nil {
								log.Printfln("处理[%s]失败: %v", fiPath, e)
							}
						}
					}
				} else {
					if e := dealFile(input, opt); e != nil {
						log.Printfln("处理[%s]失败: %v", input, e)
					}
				}
			}
		}
		return nil
	},
}
